import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'package:wk_robot2/app/blt/BltManager.dart';
import 'package:wk_robot2/app/blt/protobuf/BleBindOrSwitchWifi.pb.dart';
import 'package:wk_robot2/app/blt/protobuf/BluetoothHandShake.pb.dart';
import 'package:wk_robot2/app/blt/protobuf/CodeMao_Message.pb.dart';
import 'package:wk_robot2/app/blt/protobuf/CodeMao_MessageHeader.pb.dart';
import 'package:wk_robot2/app/utils/CommonUtil.dart';

import '../const/AppConst.dart';
import '../event/DataCallBack.dart';
import 'dart:math';

import '../logger/Logger.dart';
import '../storage/StorageManager.dart';

class HardwareCommands {

  static const services = ['2902', '2902', '2902'];
  static final writeUUID = '2902'.formattedUUID();
  static final readUUID = '2902'.formattedUUID();

  //机器人指令.
  static final int ROBOT_COMMAND_VERSION = 168;
  static final String DATA_COMMAND = "co";//蓝牙传输指令
  static final int CONNECT_SUCCESS = 4;//蓝牙连接成功指令
  static final int ROBOT_WIFI_IS_OK_TRANS = 5; //机器人是否在线
  static final int WIFI_LIST_TRANS = 1;// WiFi列表的请求和响应

  static const int WIFI_INFO_TRANS_FOR_BAINGD = 21;// 绑定联网
  static const int WIFI_INFO_TRANS = 2;// WIFI 信息发送
  static const int BINDING_AGENT_TOKEN = 11; // AgentToken的刷新.
  static const int BINDING_UBT_SUCCESS = 9;//绑定ubt后台成功指令,目前用于机器人播报绑定成功

  static const String SUCCESS_COMMAND = "s";// 机器人响应的WiFi列表

  // 第一个指令0握手, 发送已经握手.32/4  ->配对成功<-, 发送检查网络指令 32/5,  获取wifi 32/1,
  // 设置网络密码, 调用绑定接口.

  //协议头指令.
  static final int BL_NEW_HAND_SHAKE_REQUEST = 0;// 新握手
  static final int BL_BIND_OR_SWITCH_WIFI_REQUEST = 32; //配网绑定相关


  static final int PACK_LIMIT = 16; // 假设这是你的分包限制，需要定义



  static HardwareCommands? _instance;
  static HardwareCommands get instance => _instance ??= HardwareCommands();


  static Map<int,DataCallBack> dataCallBackMap = Map<int,DataCallBack>();
  static int currentGlobalSendSequence = 0;


  static final String SCAN_DEVICE_ERROR_NO_FOUND = 'NOFOUND'; //未找到设备.

  static final String SCAN_DEVICE_RECONNECTED = 'RECONNECTED'; //设备连接失败需要重更新扫描连接.

  String pactkCommandToRobot(int commendType) {
    return json.encode({
      DATA_COMMAND: commendType
    });

  }


  String setWifiPasswdInfo(String type, String name, String passwd, {int co = WIFI_INFO_TRANS_FOR_BAINGD}) {
    return json.encode({
       'c': type,
       's': name,
       'p': passwd,
       'co': co
    });
  }


  String packtAgentTokenCommandToRobot(String agentToken, String agentRefreshToken) {
    return json.encode({
      DATA_COMMAND: BINDING_AGENT_TOKEN,
      'agentToken':agentToken,
      'agentRefreshToken':agentRefreshToken
    });

  }

  String pacKBindingResultCommandToRobot(bool success, String agentToken, String agentRefreshToken) {
    String bindResult = "1";
    if (!success) {
      bindResult = "0";
    }

    return json.encode({
      DATA_COMMAND : BINDING_UBT_SUCCESS,
      SUCCESS_COMMAND: bindResult,
      'agentToken':agentToken,
      'agentRefreshToken':agentRefreshToken
    });


  }


  void sendMsgToRobot (Map<String,dynamic> headerMp, Uint8List requestBody, DataCallBack dataCallBack) {

    print('requestBody data : ${CommonUtil.uint8ListToHex(requestBody)}');
    MessageHeader messageHeader =  MessageHeader.create();

    // 因为java和dart的PB实现差异, 需要在dart里面判断int !=0 再参与编码.
    if (headerMp[AppConst.PROTOCOL_HEADER_COMMADN] != 0) { // 指令类型
      messageHeader.commandId = headerMp[AppConst.PROTOCOL_HEADER_COMMADN];
    }

    if (headerMp[AppConst.PROTOCOL_RPOTO_VERSION] != 0) { // 客户端平台类型
      messageHeader.versionCode = headerMp[AppConst.PROTOCOL_RPOTO_VERSION];
    }


    if (headerMp[AppConst.PROTOCOL_REQUEST_SEQUENCE] != 0) { // 请求序列.
      messageHeader.sendSerial = headerMp[AppConst.PROTOCOL_REQUEST_SEQUENCE];
    }
    if (headerMp[AppConst.PROTOCOL_RESPONSE_SEQUENCE] != 0) { // 响应序列.
      messageHeader.responseSerial = headerMp[AppConst.PROTOCOL_RESPONSE_SEQUENCE];
    }

    dataCallBackMap[messageHeader.sendSerial] = dataCallBack;
    currentGlobalSendSequence = messageHeader.sendSerial;

    print('header data : ${CommonUtil.uint8ListToHex(messageHeader.writeToBuffer())}');

    Message message = Message()
      ..header = messageHeader;

    if(!requestBody.isEmpty) {
      message.bodyData = requestBody;
    }

    print('message data : ${CommonUtil.uint8ListToHex(message.writeToBuffer())}');

    //组装pack.
    Uint8List finalData =  pack(message.writeToBuffer());

    print('finalData data : ${CommonUtil.uint8ListToHex(finalData)}, commandId: ${messageHeader.commandId}');

   // readSomethingFromBtl(finalData);

    writeData(finalData,dataCallBack!);
  }





 int getRequestSequence() {
    if (StorageManager.getStorage().hasData(AppConst.storage_blt_request_sequence)) {
      int sequence = StorageManager.getStorage().read(AppConst.storage_blt_request_sequence)  + 1;
      StorageManager.getStorage().write(AppConst.storage_blt_request_sequence, sequence);
      return sequence;
    } else {
      StorageManager.getStorage().write(AppConst.storage_blt_request_sequence, 1);
      return 1;
    }
  }

  int getResponseSequence() {
    if (StorageManager.getStorage().hasData(AppConst.storage_blt_response_sequence)) {
      int sequence = StorageManager.getStorage().read(AppConst.storage_blt_response_sequence)  + 1;
      StorageManager.getStorage().write(AppConst.storage_blt_response_sequence, sequence);
      return sequence;
    } else {
      StorageManager.getStorage().write(AppConst.storage_blt_response_sequence, 0);
      return 0;
    }
  }


  Uint8List pack(Uint8List pendingPackData) {
      // header 2 byte, version 1 byte, 数据长度2 byte, 数据内容长度 x byte, checksum 1 byte. pack end 1
      int byteArrayLength = pendingPackData.length + 7;
      Uint8List packedCommandByte  = Uint8List(byteArrayLength);

      // 协议头 2.
      packedCommandByte[0] = 0xfb;
      packedCommandByte[1] = 0xbf;

      //协议版本 1.
      packedCommandByte[2] = 0x01;
      //数据长度 2.
      Uint8List dataLengthByte = CommonUtil.intToByteArray(byteArrayLength-1, 2); // -1 去掉pack的尾部字节.
      packedCommandByte[3] = dataLengthByte[0];
      packedCommandByte[4] = dataLengthByte[1];

      //数据内容.
      for (int i = 0; i < pendingPackData.length; i++) {
        packedCommandByte[i+5] = pendingPackData[i];
      }

      // packedCommandByte.setRange(5, dateLenth - commandsData.length , commandsData);
      packedCommandByte[byteArrayLength-2] = 1;

      // 添加pack结束标记为. 0xed
      packedCommandByte[byteArrayLength-1] = 0xed;

      return packedCommandByte;
  }


  // 打包蓝牙btl指令.
  Uint8List packBltData(Uint8List commandsData) {
    // header 2 byte, version 1 byte, 数据长度2 byte, 数据内容长度 x byte, checksum 1 byte. packend 1
    int dateLenth = commandsData.length + 7;
    Uint8List packedCommandByte  = Uint8List(dateLenth);
    int packLength = commandsData.length + 6;
    // 协议头 2.
    packedCommandByte[0] = 0xfb;
    packedCommandByte[1] = 0xbf;

    //协议版本 1.
    packedCommandByte[2] = 0x01;
    //数据长度 2.
    Uint8List dataLengthByte = CommonUtil.intToByteArray(dateLenth, 2);
    packedCommandByte[3] = dataLengthByte[0];
    packedCommandByte[4] = dataLengthByte[1];

    //数据内容.
    for (int i = 0; i < commandsData.length; i++) {
      packedCommandByte[i+5] = commandsData[i];
    }

    //计算checksum.
    int paramSum = 0;
    for (int i = 0; i <commandsData.length; i++) {
      paramSum = paramSum + commandsData[i];
    }

    packedCommandByte[dateLenth-2] = packLength + paramSum;


    // 添加pack结束标记为. 0xed
    packedCommandByte[dateLenth-1] = 0xed;

    return packedCommandByte;
  }



  Uint8List shortToByteArray(int value) {
    Uint8List result = Uint8List(2);
    result[0] = (value >> 8) & 0xFF;
    result[1] = value & 0xFF;
    return result;
  }

  //切割数据.
  Queue<Uint8List> divideData (Uint8List data) {
    Random random = Random();
    //32767 short.MAX最大值.
    List<int> randomValue = shortToByteArray(random.nextInt(32767) & 0xFFFF); // Dart 的 Random.nextInt 是 int 类型，需要限制在 Short.MAX_VALUE 范围内

    int serialNo = 1;
    if (data.length <= HardwareCommands.PACK_LIMIT) {
      Queue<Uint8List> dataList = Queue<Uint8List>();
      Uint8List packet = Uint8List(data.length + 2 + 2); // 原始数据 + 随机值 + 序列号
      packet.setAll(0, data);
      packet.setAll(data.length, randomValue);
      packet.setAll(data.length + randomValue.length, shortToByteArray(serialNo));
      dataList.add(packet);
      return dataList;
    } else {
      Queue<Uint8List> res = Queue<Uint8List>();
      int n = data.length ~/ HardwareCommands.PACK_LIMIT;

      for (int i = 0; i < n; i++) {
        Uint8List packet = Uint8List(HardwareCommands.PACK_LIMIT + 2 + 2); // 每包数据 + 随机值 + 序列号
        packet.setAll(0, data.sublist(i * HardwareCommands.PACK_LIMIT, (i + 1) * HardwareCommands.PACK_LIMIT));
        packet.setAll(HardwareCommands.PACK_LIMIT, randomValue);
        packet.setAll(HardwareCommands.PACK_LIMIT + randomValue.length, shortToByteArray(serialNo++));
        res.add(packet);
      }

      if (data.length % HardwareCommands.PACK_LIMIT != 0) {
        Uint8List lastPacket = Uint8List((data.length % HardwareCommands.PACK_LIMIT) + 2 + 2); // 剩余数据 + 随机值 + 序列号
        lastPacket.setAll(0, data.sublist(n * HardwareCommands.PACK_LIMIT));
        lastPacket.setAll(data.length % HardwareCommands.PACK_LIMIT, randomValue);
        lastPacket.setAll((data.length % HardwareCommands.PACK_LIMIT) + randomValue.length, shortToByteArray(serialNo++));
        res.add(lastPacket);
      }

      return res;
    }
  }


  // 写入数据的函数
  void writeData(Uint8List rawData,DataCallBack dataCallBack) async {
    Queue<Uint8List>  mDataQueue =  divideData(rawData);
    logger.info('[FFFF]发送指令长度: ${mDataQueue.length}');
    int commandItem = 0;
    while (mDataQueue.isNotEmpty) {
      Uint8List data = mDataQueue.removeFirst();
      //每次写完等待0.5秒,让蓝牙不会因为大量请求而死机.
      // await Future.delayed(Duration(milliseconds: 500));
      await BltManager.instance.write(data,dataCallBack);
      commandItem  = commandItem + 1;
      logger.info('[FFFF]发送指令Index: ${commandItem}');

    }
  }



}


extension BLEFormat on String {
  String formattedUUID() {
    return '0000$this-0000-1000-8000-00805f9b34fb';
  }
}



